package dexter.net;

import java.net.InetSocketAddress;

import org.apache.mina.common.ConnectFuture;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.transport.socket.nio.SocketConnector;
import org.apache.mina.transport.socket.nio.SocketConnectorConfig;

import dexter.core.host.HostAddress;
import dexter.net.msg.AbstractMessage;
import dexter.net.msg.common.ResponseListener;
import dexter.net.msg.common.RequestParams;


public class Producer {

	private static final int CONNECT_TIMEOUT = 30; // seconds
	
	private String HOSTNAME = "localhost";
	private int PORT = 5555;
	
	private SocketConnector connector;
	private SocketConnectorConfig cfg;

	public Producer() {
        init();
	}
	
	public Producer(String hostname, int port ) {
		
		HOSTNAME = hostname;
		PORT = port;

        init();
	}
	
	public Producer(HostAddress host) {
		HOSTNAME = host.getAddress().getHostName();
		PORT = host.getAddress().getPort();
	
		init();
	}

	private void init() {

        connector = new SocketConnector();

        // Change the worker timeout to 1 second to make the I/O thread quit soon
        // when there's no connection to manage.
        connector.setWorkerTimeout(1);

        // Configure the service.
        cfg = new SocketConnectorConfig();
        cfg.setConnectTimeout(CONNECT_TIMEOUT);
        cfg.getFilterChain().addLast(
                    "codec",
                    new ProtocolCodecFilter(
                            new ObjectSerializationCodecFactory()));
        
        //cfg.getFilterChain().addLast("logger", new LoggingFilter());
	}
	
	public void send(RequestParams params, ResponseListener listener) {
		
		IoSession session;
		
		ConnectFuture future = connector.connect(new InetSocketAddress(
                HOSTNAME, PORT), new ProducerSessionHandler(params, listener), cfg);

        future.join();
        session = future.getSession();
        
        // wait until the summation is done
        session.getCloseFuture().join();
       
	}
	
	public void send(HostAddress host, final AbstractMessage msg) {
		
        IoSession session;        
		
		ConnectFuture future = connector.connect(host.getAddress(),	new IoHandlerAdapter() {
			  public void sessionOpened(IoSession session) {
			        session.write(msg);    
			    }
		}, cfg);

        future.join();
        session = future.getSession();
        // wait until the summation is done
        session.close();
        //session.getCloseFuture().join();
		
	}
	
//	public void send(final RequestMessage msg) {
//		
//		IoSession session;        
//		
//		ConnectFuture future = connector.connect(new InetSocketAddress(
//                HOSTNAME, PORT),	new IoHandlerAdapter() {
//			  public void sessionOpened(IoSession session) {
//			        session.write(msg);    
//			    }
//		}, cfg);
//
//        future.join();
//        session = future.getSession();
//
//        session.close();
//       
//	}
   
}
